package controllers

import (
	"encoding/json"
	"github.com/astaxie/beego"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/gorilla/websocket"
	"hello/lib/mqttLib"
	"log"
	"net/http"
)

type MqttWebsocket struct {
	beego.Controller
}

type WsConn struct {
	ws *websocket.Conn
	mc mqtt.Client
	gw string
	uid string
	broadcast chan DeviceData
}
var (
	broadcast = make(chan DeviceData, 100)
)
var wsUpgrader = websocket.Upgrader{
	ReadBufferSize: 1024,
	WriteBufferSize: 1024,
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}
var clients = make(map[*WsConn]bool)
func (mw *MqttWebsocket) Get() {
	mw.EnableRender = false
	ws, err := wsUpgrader.Upgrade(mw.Ctx.ResponseWriter, mw.Ctx.Request, nil)

	//defer ws.Close()
	if err != nil {
		log.Fatal(err)
	}
	gatewayId := mw.GetString("gateway_id")
	userId := mw.GetString("user_id")
	wsConn := &WsConn{
		broadcast: make(chan DeviceData, 100),
	}
	// connect mqtt and get data
	c := mqttLib.NewMqttClient(mqttLib.DefaultMqttconfig, wsConn.onMqttMsgHandler)
	//defer c.Disconnect(1000*10)
	topic := gatewayId + "/data"
	log.Printf("topic:   %s", topic)
	if token := c.Connect(); token.Wait() && token.Error() != nil {
		log.Printf("mqtt client connect error :%s", token.Error())
	}
	if token := c.Subscribe(topic, 0, nil); token.Wait() && token.Error() != nil {
		log.Print("test sub")
	}
	wsConn.ws = ws
	wsConn.gw = gatewayId
	wsConn.mc = c
	wsConn.uid = userId

	clients[wsConn] = true
	go wsConn.HandleMessage()

	//ws.ReadMessage()
	// response websocket
	defer wsConn.ws.Close()
	defer wsConn.mc.Disconnect(10*1000)
}
func (wsConn *WsConn)onMqttMsgHandler(client mqtt.Client, msg mqtt.Message) {
	var deviceData DeviceData

	data := msg.Payload()
	if err := json.Unmarshal(data, &deviceData); err != nil {
		log.Printf("unmarshal mqtt message error: %s", err.Error())
	}
	log.Printf("mqtt data is:%s", string(data))
	wsConn.broadcast <- deviceData
	log.Print("test=====test")

}
func (wsConn *WsConn) HandleMessage() {
	for {
		log.Print("ws gofunc")
		msg := <- wsConn.broadcast
		m, _ := json.Marshal(msg)
		log.Printf("msg is :%s", string(m))
		err := wsConn.ws.WriteJSON(msg)
		if err != nil {
			log.Printf("write message error: %s", err.Error())
			break
		}
	}
}